#include "cJSON.h"
#include "esp_coexist.h"
#include "esp_flash.h"
#include "tb_mqtt_client.h"
#include "tb_rpc.h"
#include "wifi_manager.h"
#include "zigbee_manager.h"
#include <stdio.h>
#define TAG "app_main"
#define CONFIG_BUTTON GPIO_NUM_9

bool zigbee_is_init = false;

static void on_zigbee_start(void) { printf("Zigbee 启动成功！\n"); }

void report_to_thingsboard_task() {
	for (int i = 0; i < MAX_DEVICES; i++) {
	}
}

static void on_device_join(uint16_t short_addr, esp_zb_ieee_addr_t ieee_addr) {
	LedConfig led_config = {.interval = 0,
							.mode = LED_BREATH_PWM,
							.pin = GPIO_NUM_6,
							.pwm_channel = LEDC_CHANNEL_3};
	LedConfig led_config1 = {.interval = 0,
							 .mode = LED_BREATH_PWM,
							 .pin = GPIO_NUM_7,
							 .pwm_channel = LEDC_CHANNEL_4};

	char ieee_str[17];
	snprintf(ieee_str, sizeof(ieee_str), "%02X%02X%02X%02X%02X%02X%02X%02X",
			 ieee_addr[7], ieee_addr[6], ieee_addr[5], ieee_addr[4],
			 ieee_addr[3], ieee_addr[2], ieee_addr[1], ieee_addr[0]);

	ESP_LOGI(TAG, "Device joined, short_addr: 0x%04X, IEEE: %s", short_addr,
			 ieee_str);
	if (strcmp(ieee_str, "E4B323FFFEB6E62C") == 0) {
		led_manager_set_mode(led_config);
	} else {
		led_manager_set_mode(led_config1);
	}

	char json[64];
	snprintf(json, sizeof(json), "{\"%s\":true}", ieee_str);
	tb_send_telemetry(json);
}

static void on_device_leave(uint16_t short_addr, esp_zb_ieee_addr_t ieee_addr) {
	LedConfig led_config = {.interval = 0,
							.mode = LED_BREATH_PWM,
							.pin = GPIO_NUM_6,
							.pwm_channel = LEDC_CHANNEL_3};
	LedConfig led_config1 = {.interval = 0,
							 .mode = LED_BREATH_PWM,
							 .pin = GPIO_NUM_7,
							 .pwm_channel = LEDC_CHANNEL_4};

	char ieee_str[17];
	snprintf(ieee_str, sizeof(ieee_str), "%02X%02X%02X%02X%02X%02X%02X%02X",
			 ieee_addr[7], ieee_addr[6], ieee_addr[5], ieee_addr[4],
			 ieee_addr[3], ieee_addr[2], ieee_addr[1], ieee_addr[0]);

	ESP_LOGI(TAG, "Device leave, short_addr: 0x%04X, IEEE: %s", short_addr,
			 ieee_str);
	if (strcmp(ieee_str, "E4B323FFFEB6E62C") == 0) {
		led_config.mode = LED_OFF;
		led_manager_set_mode(led_config);
	} else {
		led_config1.mode = LED_OFF;
		led_manager_set_mode(led_config1);
	}

	char json[64];
	snprintf(json, sizeof(json), "{\"%s\":false}", ieee_str);
	tb_send_telemetry(json);
}

esp_err_t
zb_attribute_reporting_handler(esp_zb_zcl_report_attr_message_t *msg) {
	if (!msg || msg->attribute.data.size == 0) {
		ESP_LOGW(TAG, "无效的属性上报结构体");
		return ESP_FAIL;
	}

	ESP_LOGI(TAG, "Free Heap: %08X",(unsigned int) esp_get_free_heap_size());
	char ieee_str[17];
	if (!get_esp_zb_ieee_addr(msg->src_address.u.short_addr, ieee_str,
							  sizeof(ieee_str))) {
		ESP_LOGI(TAG, "is not device: 0x%04X", msg->src_address.u.short_addr);
		return ESP_FAIL;
	}

	uint16_t cluster_id = msg->cluster;
	uint16_t attr_id = msg->attribute.id;

	cJSON *root = cJSON_CreateObject();
	char key[64];
	switch (cluster_id) {
	case ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT:
		if (attr_id == ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID) {
			int16_t temp_raw = *(int16_t *)msg->attribute.data.value;
			snprintf(key, sizeof(key), "%s_temperature", ieee_str);
			cJSON_AddNumberToObject(root, key, temp_raw / 100.0);
		}
		break;

	case ESP_ZB_ZCL_CLUSTER_ID_REL_HUMIDITY_MEASUREMENT:
		if (attr_id == ZB_ZCL_ATTR_REL_HUMIDITY_MEASUREMENT_VALUE_ID) {
			uint16_t humi_raw = *(uint16_t *)msg->attribute.data.value;
			snprintf(key, sizeof(key), "%s_humidity", ieee_str);
			cJSON_AddNumberToObject(root, key, humi_raw / 100.0);
		}
		break;

	case ESP_ZB_ZCL_CLUSTER_ID_ILLUMINANCE_MEASUREMENT:
		if (attr_id == ZB_ZCL_ATTR_ILLUMINANCE_MEASUREMENT_MEASURED_VALUE_ID) {
			uint16_t lux = *(uint16_t *)msg->attribute.data.value;
			snprintf(key, sizeof(key), "%s_light", ieee_str);
			cJSON_AddNumberToObject(root, key, lux);
		}
		break;

	default:
		if (cluster_id == 0xFC01) {
			uint16_t lux = *(uint16_t *)msg->attribute.data.value;
			snprintf(key, sizeof(key), "%s_soil", ieee_str);
			cJSON_AddNumberToObject(root, key, lux);
		} else {
			ESP_LOGW(TAG, "未知集群上报: 0x%04X, 属性: 0x%04X", cluster_id,
					 attr_id);;
			cJSON_Delete(root);
			return ESP_FAIL;
		}
	}
	char *json_str = cJSON_PrintUnformatted(root);
	tb_send_telemetry(json_str);
	free(json_str);
	cJSON_Delete(root);
	return ESP_OK;
}

static const char *handle_off_on_rpc(cJSON *params) {
	cJSON *ieee_item = cJSON_GetObjectItem(params, "ieee_addr");
	const char *target_ieee = ieee_item->valuestring;
	zigbee_device_info_t *ieee_str = get_esp_zb_short(target_ieee);
	if (ieee_str != NULL) {
		// esp_zb_zcl_on_off_cmd_t cmd_req;
		// cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = ieee_str->short_addr;
		// cmd_req.zcl_basic_cmd.dst_endpoint = 10;
		// cmd_req.zcl_basic_cmd.src_endpoint = ESP_ZB_GATEWAY_ENDPOINT;
		// cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT;
		// cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_TOGGLE_ID;
		// ESP_LOGI(TAG, "command addr_short: 0x%04X dst_endpoint: %d",
		//		 cmd_req.zcl_basic_cmd.dst_addr_u.addr_short,
		//		 cmd_req.zcl_basic_cmd.dst_endpoint);
		// esp_zb_lock_acquire(portMAX_DELAY);
		// esp_zb_zcl_on_off_cmd_req(&cmd_req);
		// esp_zb_lock_release();

		cJSON *btn_switch = cJSON_GetObjectItem(params, "switch");
		int btn = btn_switch->valueint;
		if (btn == 1) {
			uint8_t payload_data[] = {0x01, 0x02};
			zigbee_send_zcl_command(ieee_str->short_addr, 10, 0xFC05,
									ESP_ZB_HA_ON_OFF_SWITCH_DEVICE_ID,
									payload_data);
		} else {
			/* code */
			uint8_t payload_data[] = {0x01, 0x02};
			zigbee_send_zcl_command(ieee_str->short_addr, 10, 0xFC06,
									ESP_ZB_HA_ON_OFF_SWITCH_DEVICE_ID,
									payload_data);
		}
		return "{\"m\":\"ok\"}";
	}
	return "{\"m\":\"fail\"}";
}

static void on_mqtt_event(esp_mqtt_event_handle_t event) {
	LedConfig led_config = {.interval = 0,
							.mode = LED_BREATH_PWM,
							.pin = GPIO_NUM_5,
							.pwm_channel = LEDC_CHANNEL_2};

	switch ((esp_mqtt_event_id_t)event->event_id) {
	case MQTT_EVENT_CONNECTED:
		led_config.mode = LED_BREATH_PWM;
		led_manager_set_mode(led_config);
		break;
	case MQTT_EVENT_DISCONNECTED:
		led_config.interval = 200;
		led_config.mode = LED_BLINK;
		led_manager_set_mode(led_config);
		break;
	default:
		break;
	}
}

/**
 * wifi连接事件
 */
static void ip_event_handler(void *arg, esp_event_base_t event_base,
							 int32_t event_id, void *event_data) {
	LedConfig led_config = {.interval = 0,
							.mode = LED_BREATH_PWM,
							.pin = GPIO_NUM_4,
							.pwm_channel = LEDC_CHANNEL_1};

	if (event_id == IP_EVENT_STA_GOT_IP) {
		ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data;
		ESP_LOGI(TAG, "Got IP: " IPSTR, IP2STR(&event->ip_info.ip));
		// 开始连接 MQTT
		tb_mqtt_start(get_mqtt_uri(), get_mqtt_token(), on_mqtt_event);
		tb_rpc_subscribe("off_on", handle_off_on_rpc);

		if (!zigbee_is_init) {
			zigbee_is_init = true;
			// 初始化并启动 Zigbee 协调器任务
			ESP_ERROR_CHECK(zigbee_manager_init());
		}
		LedConfig led_config_1 = {
			.interval = 200, .mode = LED_BLINK, .pin = GPIO_NUM_5};
		led_manager_set_mode(led_config_1);
	} else {
		led_config.interval = 200;
		led_config.mode = LED_BLINK;
	}
	led_manager_set_mode(led_config);
}

/**
 * 长按boot进入配网模式
 */
static void monitor_config_button_task(void *arg) {
	const TickType_t delay = pdMS_TO_TICKS(100);
	const TickType_t long_press_threshold = pdMS_TO_TICKS(3000); // 3秒长按

	TickType_t press_start = 0;
	bool button_was_pressed = false;
	bool already_triggered = false;

	while (1) {
		bool pressed = gpio_get_level(CONFIG_BUTTON) == 0;

		if (pressed) {
			if (!button_was_pressed) {
				// 刚按下，记录起始时间
				press_start = xTaskGetTickCount();
				button_was_pressed = true;
			} else {
				// 一直按着，检查是否超过时间
				if (!already_triggered && (xTaskGetTickCount() - press_start >=
										   long_press_threshold)) {

					ESP_LOGI(TAG,
							 "Long press detected, restarting for config mode");
					already_triggered = true;
					esp_restart(); // 重启设备进入配网
				}
			}
		} else {
			// 按钮松开，状态重置
			button_was_pressed = false;
			already_triggered = false;
		}

		vTaskDelay(delay);
	}
}

void app_main(void) {

	// gpio_set_level(GPIO_NUM_3, 0);
	// vTaskDelay(100);
	// gpio_set_level(GPIO_NUM_14, 1);

	startLedManagerTask(20);
	addLedWithInit(GPIO_NUM_4);
	addLedWithInit(GPIO_NUM_5);
	addLedWithInit(GPIO_NUM_6);
	addLedWithInit(GPIO_NUM_7);
	addLedWithInit(GPIO_NUM_20);
	addLedWithInit(GPIO_NUM_21);
	addLedWithInit(GPIO_NUM_22);
	addLedWithInit(GPIO_NUM_23);
	LedConfig led_flow_configs[] = {{.pin = GPIO_NUM_4, .mode = LED_FLOW},
									{.pin = GPIO_NUM_5, .mode = LED_FLOW},
									{.pin = GPIO_NUM_6, .mode = LED_FLOW},
									{.pin = GPIO_NUM_7, .mode = LED_FLOW},
									{.pin = GPIO_NUM_20, .mode = LED_FLOW},
									{.pin = GPIO_NUM_21, .mode = LED_FLOW},
									{.pin = GPIO_NUM_22, .mode = LED_FLOW},
									{.pin = GPIO_NUM_23, .mode = LED_FLOW}};

	if (gpio_get_level(CONFIG_BUTTON) == 0) {
		ESP_LOGI(TAG, "start ap and web config.....");
		for (int i = 0;
			 i < sizeof(led_flow_configs) / sizeof(led_flow_configs[0]); i++) {
			led_manager_set_mode(led_flow_configs[i]);
		}

		led_manager_set_flow_direction(true);
		led_manager_set_flow_interval(200);
		launch_wifi_ap_with_web_config();
		return;
	}

	led_flow_configs[0].mode = LED_BLINK;
	led_flow_configs[0].interval = 100;
	led_manager_set_mode(led_flow_configs[0]);
	// 注册回调
	zigbee_register_callbacks(on_zigbee_start, on_device_join, on_device_leave,
							  zb_attribute_reporting_handler);

	esp_wifi_set_max_tx_power(78);
	wifi_manager_init();
	wifi_manager_begin();
	esp_coex_wifi_i154_enable();

	ESP_ERROR_CHECK(esp_event_handler_instance_register(
		IP_EVENT, IP_EVENT_STA_GOT_IP, &ip_event_handler, NULL, NULL));

	xTaskCreate(monitor_config_button_task, "btn_monitor", 6144, NULL, 5, NULL);
}
